package com.skyline.common.tag;

import java.io.IOException;
import java.io.Reader;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.taglibs.standard.tag.common.core.Util;

import com.skyline.common.util.WebHelper;

public class SessionAttributeTag extends TagSupport {
	private static final long serialVersionUID = -8982295995751122758L;
	private static final Log LOGGER = LogFactory.getLog(SessionAttributeTag.class);
	private String key;
	private boolean escapeXml;

	public SessionAttributeTag() {
		super();
	}

	public void setEscapeXml(boolean escapeXml) {
		this.escapeXml = escapeXml;
	}

	public void setKey(String key) {
		this.key = key;
	}

	@Override
	public int doEndTag() throws JspException {
		HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();
		Object value = WebHelper.getSessionAttribute(request, key);
		try {
			out(pageContext, escapeXml, value);
		} catch (IOException e) {
			LOGGER.warn("调用sessionAttribute出错", e);
		}
		return EVAL_BODY_INCLUDE;
	}

	private void out(PageContext pageContext, boolean escapeXml, Object value) throws IOException {
		JspWriter out = pageContext.getOut();
		if (!escapeXml) {
			// write chars as is
			if (value instanceof Reader) {
				Reader reader = (Reader) value;
				char[] buf = new char[4096];
				int count = 0;
				while ((count = reader.read(buf, 0, 4096)) != -1) {
					out.write(buf, 0, count);
				}
			} else {
				out.write(value==null?"":value.toString());
			}
		} else {
			// escape XML chars
			if (value instanceof Reader) {
				Reader reader = (Reader) value;
				char[] buf = new char[4096];
				int count = 0;
				while ((count = reader.read(buf, 0, 4096)) != -1) {
					writeEscapedXml(buf, count, out);
				}
			} else {
				String text = value.toString();
				writeEscapedXml(text.toCharArray(), text.length(), out);
			}
		}
	}

	/**
	 * 
	 * Optimized to create no extra objects and write directly to the JspWriter
	 * using blocks of escaped and unescaped characters
	 * 
	 */
	private static void writeEscapedXml(char[] buffer, int length, JspWriter w) throws IOException {
		int start = 0;

		for (int i = 0; i < length; i++) {
			char c = buffer[i];
			if (c <= Util.HIGHEST_SPECIAL) {
				char[] escaped = Util.specialCharactersRepresentation[c];
				if (escaped != null) {
					// add unescaped portion
					if (start < i) {
						w.write(buffer, start, i - start);
					}
					// add escaped xml
					w.write(escaped);
					start = i + 1;
				}
			}
		}
		// add rest of unescaped portion
		if (start < length) {
			w.write(buffer, start, length - start);
		}
	}
}
